#ifndef EVENT_BUS_H
#define EVENT_BUS_H

/**
 * @file event_bus.h
 * @brief 发布-订阅事件总线的声明。
 *
 * 提供订阅、发布、停止运行等接口，内部使用单独线程异步分发消息。
 */

#include <atomic>
#include <functional>
#include <shared_mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>

#include "blocking_queue.h"
#include "message.h"
#include "subscription.h"

/**
 * @class EventBus
 * @brief 线程安全的发布-订阅中心。
 *
 * - Subscribe()：注册回调，返回 Subscription，用于退订。
 * - Publish()：推送消息，异步传递给订阅者。
 * - Stop()：停止消息循环，清空订阅者。
 */
class EventBus {
public:
    using Callback = std::function<void(const Message&)>;

    EventBus();
    ~EventBus();

    EventBus(const EventBus&) = delete;
    EventBus& operator=(const EventBus&) = delete;

    /**
     * @brief 订阅某主题。
     *
     * @param topic  主题名称。
     * @param cb     回调函数，会在消息线程中被调用。
     * @return Subscription 对象，在析构或 Reset 时退订。
     */
    Subscription Subscribe(std::string topic, Callback cb);

    /**
     * @brief 发布消息，非阻塞，将消息推入内部队列。
     *
     * @param topic   消息主题。
     * @param payload 消息内容。
     */
    void Publish(std::string topic, std::string payload);

    /**
     * @brief 停止消息分发线程并清空订阅者。
     *
     * 可多次调用，只有第一次有效。
     */
    void Stop();

    /**
     * @brief 退订指定主题的某个订阅，供 Subscription 调用。
     */
    void Unsubscribe(const std::string& topic, std::size_t id);

private:
    struct Subscriber {
        std::size_t id;
        Callback cb;
    };

    /**
     * @brief 工作线程主循环，从队列取消息并分发。
     *
     * 仅在构造函数中启动一次，在 Stop() 中收尾。
     */
    void DispatchLoop();

    BlockingQueue<Message> queue_;  ///< 待分发消息队列。
    std::atomic<std::size_t> next_id_{1};  ///< 全局递增的订阅 ID。
    std::unordered_map<std::string, std::vector<Subscriber>> subscribers_;  ///< 主题 -> 订阅者列表。
    std::shared_mutex subs_mutex_;  ///< 保护 subscribers_ 的读写锁。

    std::atomic<bool> stopped_{false};  ///< 是否已停止分发。
    std::thread worker_;                ///< 消息分发线程。
};

#endif  // EVENT_BUS_H